<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      let origin = {
        key: "BTC-15OCT21-48000-P",
        requiredMargin: "0.00",
        title: "15OCT21-48000",
      };
      let compare = {
        key: "BTC-15OCT21-48000-P",
        requiredMargin: "0.00",
        title: "15OCT21-48000",
      };
      var start = Date.now();
      for (let index = 0; index < 10000000; index++) {
        let copy = JSON.parse(JSON.stringify(origin));
      }
      console.log("deep copy time1", Date.now() - start);

      var start = Date.now();
      for (let index = 0; index < 10000000; index++) {
        let copy = Object.assign({}, {}, origin);
      }
      console.log("deep copy time2", Date.now() - start);

      var start = Date.now();
      function deepClone(value, hash = new WeakMap()) {
        // 弱引用，不要用map
        // null 和 undefiend 是不需要拷贝的
        if (value == null) {
          return value;
        }
        if (value instanceof RegExp) {
          return new RegExp(value);
        }
        if (value instanceof Date) {
          return new Date(value);
        }
        // 函数是不需要拷贝
        if (typeof value != "object") return value;
        let obj = new value.constructor(); // [] {}
        // 说明是一个对象类型
        if (hash.get(value)) {
          return hash.get(value);
        }
        hash.set(value, obj);
        for (let key in value) {
          // in 会遍历当前对象上的属性 和 __proto__指代的属性
          // 补考呗 对象的__proto__上的属性
          if (value.hasOwnProperty(key)) {
            // 如果值还有可能是对象 就继续拷贝
            obj[key] = deepClone(value[key], hash);
          }
        }
        return obj;
        // 区分对象和数组 Object.prototype.toString.call
      }
      for (let index = 0; index < 10000000; index++) {
        let copy = deepClone(origin);
      }
      console.log("deep copy time3", Date.now() - start);

      var start = Date.now();
      var count = 0;
      for (let index = 0; index < 10000000; index++) {
        let originStr = JSON.stringify(origin);
        let compareStr = JSON.stringify(compare);
        if (originStr === compareStr) {
          count++;
        }
      }
      console.log("deep compare time1", Date.now() - start, count);

      const deepEqual = (x, y) => {
        // 指向同一内存时
        if (x === y) {
          return true;
        } else if (
          typeof x == "object" &&
          x != null &&
          typeof y == "object" &&
          y != null
        ) {
          if (Object.keys(x).length !== Object.keys(y).length) {
            return false;
          }
          for (const prop in x) {
            // eslint-disable-next-line no-prototype-builtins
            if (y.hasOwnProperty(prop)) {
              if (!deepEqual(x[prop], y[prop])) return false;
            } else {
              return false;
            }
          }
          return true;
        } else {
          return false;
        }
      };

      var start = Date.now();
      var count = 0;
      for (let index = 0; index < 10000000; index++) {
        if (deepEqual(origin, compare)) count++;
      }
      console.log("deep compare time2", Date.now() - start, count);
    </script>
  </body>
</html>
